/*
 * Copyright 2000-2020 ALPHA LAB.Inc All Rights Reserved.
 */
package com.alphalab.framework.dao;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set; 
import org.hibernate.Query; 
import org.hibernate.transform.Transformers;
import org.springframework.transaction.annotation.Transactional;
import com.alphalab.framework.domain.BaseEntity;
import com.alphalab.framework.domain.QueryOption;
import com.alphalab.framework.exception.MoDaoException;
import com.alphalab.framework.log.IMoLog;
import com.alphalab.framework.log.MoLogFactory;
import com.alphalab.framework.util.StringUtil; 
import java.lang.reflect.ParameterizedType; 

/**
 * 通用的查询方法实现.
 * @author allen 
 * @version 1.0.0 2017年7月17日
 * @param <PO>
 */  
@Transactional(rollbackFor=Exception.class)
public class GeneralQueryDao<PO extends BaseEntity> extends EntityDao<PO> implements IGeneralQueryDao<PO> {

	/**
	 * logger.
	 */
	private static final IMoLog logger = MoLogFactory.getLog(GeneralQueryDao.class);
	
	/**
	 * entityClass.
	 */
	private final Class<PO> entityClass;
	
	/**
	 * GeneralQueryDao构造函数，初始化entityClass. 
	 */
	public GeneralQueryDao() { 
		//常见的hibernate的取得子类class的方法
		try {
			entityClass = (Class<PO>) ((ParameterizedType) getClass()
			        .getGenericSuperclass()).getActualTypeArguments()[0]; 
		} catch (Exception ex) {
			//为防子类继承不规范，故加上异常提示处理
			final String clsName = getClass().getSimpleName();
			final int subLength = 3;
			logger.error("初始化GeneralQueryDao失败", ex);
			throw new MoDaoException(getClass().getCanonicalName()
					+ "未定义泛型! 继承于:" + GeneralQueryDao.class.getCanonicalName()
					+ "的类都必需声明所操作实体的泛型, 如:\npublic class " + clsName
					+ " extends " + GeneralQueryDao.class.getSimpleName() + "<"
					+ clsName.substring(0, clsName.length() - subLength)
					+ "> implements I" + clsName + "{\n\t...\n}", ex);
		}    
	}	
	
	/**
	 * 根据查询条件返回分页结果集.
	 * @param queryOption 查询条件，为空则表示无条件
	 * @param pageIndex 第几页，从1开始
	 * @param pageSize 每页的记录总数
	 * @param orderBy 排序字段，为空表示默认排序
	 * @param isDesc 是否降序，为true表示降序
	 * @return List<PO>
	 */
	@Override
	public List<PO> findListByPageWithCondition(final QueryOption queryOption,
			final int pageIndex, final int pageSize, final String orderBy, final boolean isDesc) { 
		final StringBuffer hql = new StringBuffer(" from ").append(entityClass.getSimpleName());
		String condition = "";
		Map param = new HashMap(10);
		if (queryOption != null) {
			condition = queryOption.getHql();
			param = queryOption.getParam();
		}
		if (StringUtil.isNotEmptyString(condition)) { 
			hql.append(" where 1=1 ").append(condition.trim()); 
		}
		if (StringUtil.isNotEmptyString(orderBy)) {
			hql.append(" order by " + orderBy); 
			if (isDesc) {
				hql.append(" desc"); 
			} else {
				hql.append(" asc"); 
			}
		} 
		return findByHql(hql.toString(), param, pageIndex, pageSize);	 
	}

	/**
	 * 根据查询条件返回全部结果集.
	 * @param queryOption 查询条件，为空则表示无条件
	 * @param orderBy 排序字段，为空表示默认排序
	 * @param isDesc 是否降序，为true表示降序
	 * @return List<PO>
	 */
	@Override
	public List<PO> findListWithCondition(final QueryOption queryOption,
			final String orderBy, final boolean isDesc) { 
		final StringBuffer hql = new StringBuffer(" from ").append(entityClass.getSimpleName());
		String condition = "";
		Map param = new HashMap(10);
		if (queryOption != null) {
			condition = queryOption.getHql();
			param = queryOption.getParam();
		}
		if (StringUtil.isNotEmptyString(condition)) { 
			hql.append(" where 1=1 ").append(condition.trim()); 
		}
		if (StringUtil.isNotEmptyString(orderBy)) {
			hql.append(" order by " + orderBy); 
			if (isDesc) {
				hql.append(" desc"); 
			} else {
				hql.append(" asc"); 
			}
		} 
		return findByHql(hql.toString(), param);	
	}

	/**
	 * 根据hql查询返回全部结果集.
	 * @param hql hql
	 * @param conditions 查询参数键值对集合
	 * @return List<PO>
	 */
	@Override
	public List<PO> findByHql(final String hql, final Map<String, Object> conditions) {
		final Query query = getCurrentSession().createQuery(hql);  
	    if (conditions != null) {  
	        final Set<String> keySet = conditions.keySet();  
	        for (String key : keySet) {                    
	        	final Object obj = conditions.get(key); 
	        	if (obj instanceof Collection<?>) {
	        		query.setParameterList(key, (Collection<?>) obj); 
	        	} else if (obj instanceof Object[]) {
	        		query.setParameterList(key, (Object[]) obj); 
	        	} else {
	        		query.setParameter(key, conditions.get(key));
	        	}       
	        }  
	    }   
		return query.list();
	}

	/**
	 * 根据hql查询返回分页结果集.
	 * @param hql hql
	 * @param conditions 查询参数键值对集合
	 * @param pageIndex 第几页，从1开始
	 * @param pageSize 每页的记录总数
	 * @return List<PO>
	 */
	@Override
	public List<PO> findByHql(final String hql, final Map<String, Object> conditions,
			final int pageIndex, final int pageSize) { 
		final Query query = getCurrentSession().createQuery(hql); 	 
	    if (conditions != null) {  
	        final Set<String> keySet = conditions.keySet();  
	        for (String key : keySet) {                    
	        	final Object obj = conditions.get(key); 
	        	if (obj instanceof Collection<?>) {
	        		query.setParameterList(key, (Collection<?>) obj); 
	        	} else if (obj instanceof Object[]) {
	        		query.setParameterList(key, (Object[]) obj); 
	        	} else {
	        		query.setParameter(key, conditions.get(key));
	        	}   
	        }  
	    }  
	    if (pageIndex != 0 && pageSize != 0) {  
			int startIndex = (pageIndex - 1) * pageSize;
			if (startIndex < 0) {
				startIndex = 0;
			}	    	 
	        query.setFirstResult(startIndex);  
	        query.setMaxResults(pageSize);  
	    }  	    
		return query.list();
	}

	/**
	 * 根据原生sql查询返回全部结果集.
	 * @param sql sql
	 * @param conditions 查询条件键值对，为空则表示无条件
	 * @return List<Map>
	 */
	@Override
	public List<Map> findBySql(final String sql, final Map<String, Object> conditions) { 
		final Query query = getCurrentSession().createSQLQuery(sql)
				.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); 
	    if (conditions != null) {  
	        final Set<String> keySet = conditions.keySet();  
	        for (String key : keySet) {                    
	        	final Object obj = conditions.get(key); 
	        	if (obj instanceof Collection<?>) {
	        		query.setParameterList(key, (Collection<?>) obj); 
	        	} else if (obj instanceof Object[]) {
	        		query.setParameterList(key, (Object[]) obj); 
	        	} else {
	        		query.setParameter(key, conditions.get(key));
	        	}         
	        }  
	    }  		
		final List list = query.list();
		return list;
	}

	/**
	 * 根据原生sql查询返回分页结果集.
	 * @param sql sql
	 * @param conditions 查询条件键值对，为空则表示无条件
	 * @param pageIndex 第几页，从1开始
	 * @param pageSize 每页的记录总数
	 * @return List<Map>
	 */
	@Override
	public List<Map> findBySql(final String sql, final Map<String, Object> conditions, final int pageIndex, 
			final int pageSize) { 
		final Query query = getCurrentSession().createSQLQuery(sql)
				.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
	    if (conditions != null) {  
	        final Set<String> keySet = conditions.keySet();  
	        for (String key : keySet) {                    
	        	final Object obj = conditions.get(key); 
	        	if (obj instanceof Collection<?>) {
	        		query.setParameterList(key, (Collection<?>) obj); 
	        	} else if (obj instanceof Object[]) {
	        		query.setParameterList(key, (Object[]) obj); 
	        	} else {
	        		query.setParameter(key, conditions.get(key));
	        	}        
	        }  
	    }  				
		final List list = query.setFirstResult(pageIndex).setMaxResults(pageSize).list();
		return list;
	}
	
	/**
	 * 根据原生sql查询返回映射为实体类的结果集.
	 * @param sql sql
	 * @param conditions 查询条件键值对，为空则表示无条件 
	 * @param entityType 实体类class
	 * @return List
	 */
	@Override
	public List findBySql(final String sql, final Map<String, Object> conditions, final Class entityType) { 
		final Query query = getCurrentSession().createSQLQuery(sql).setResultTransformer(
				Transformers.aliasToBean(entityType));
	    if (conditions != null) {  
	        final Set<String> keySet = conditions.keySet();  
	        for (String key : keySet) {
	        	final Object obj = conditions.get(key); 
	        	if (obj instanceof Collection<?>) {
	        		query.setParameterList(key, (Collection<?>) obj); 
	        	} else if (obj instanceof Object[]) {
	        		query.setParameterList(key, (Object[]) obj); 
	        	} else {
	        		query.setParameter(key, conditions.get(key));
	        	}     
	        }  
	    }  		
		final List list = query.list();
		return list;
	}
	
	/**
	 * 根据原生sql查询返回映射为实体类的分页结果集.
	 * @param sql sql
	 * @param conditions 查询条件键值对，为空则表示无条件 
	 * @param entityType 实体类class
	 * @param pageIndex 第几页，从1开始
	 * @param pageSize 每页的记录总数
	 * @return List
	 */
	@Override
	public List findBySql(final String sql, final Map<String, Object> conditions, final Class entityType, 
			final int pageIndex, final int pageSize) { 
		final Query query = getCurrentSession().createSQLQuery(sql).setResultTransformer(
				Transformers.aliasToBean(entityType));
	    if (conditions != null) {  
	        final Set<String> keySet = conditions.keySet();  
	        for (String key : keySet) {                    
	        	final Object obj = conditions.get(key); 
	        	if (obj instanceof Collection<?>) {
	        		query.setParameterList(key, (Collection<?>) obj); 
	        	} else if (obj instanceof Object[]) {
	        		query.setParameterList(key, (Object[]) obj); 
	        	} else {
	        		query.setParameter(key, conditions.get(key));
	        	}       
	        }  
	    }  		
	    if (pageIndex != 0 && pageSize != 0) {  
			int startIndex = (pageIndex - 1) * pageSize;
			if (startIndex < 0) {
				startIndex = 0;
			}	    	 
	        query.setFirstResult(startIndex);  
	        query.setMaxResults(pageSize);  
	    }
		return query.list();
	}	
 
}
